package com.boarsoft.flow.demo.login;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.common.util.RandomUtil;
import com.boarsoft.flow.demo.bean.User;

public class LoginHard {
	private static final Logger log = LoggerFactory.getLogger(LoginHard.class);

	protected String encode;
	protected ExecutorService threadPool;

	public LoginHard(ExecutorService es) {
		threadPool = es;
	}

	public Long start(User u) throws InterruptedException {
		String rid = RandomUtil.randomUUID();
		// 打印日志
		log.info("Req{}: Start login", rid);
		// 登记流水
		this.logRequest(rid, u);
		// 登录
		if (this.login(u)) {
			// 检查账户资产
			long total = this.check(rid, u.getId());
			log.info("Req{}: My total asset = {}", rid, total);
			// 更新流水
			this.updateLog(rid, u);
			return total;
		}
		log.info("Req{}: Invalid login {}", rid, u.getName());
		// 更新流水
		this.updateLog(rid, u);
		return -1L;
	}

	public void updateLog(String rid, User u) {
		log.info("Update loign log {} to DB", rid);
	}

	public void logRequest(String rid, User u) {
		log.info("Log loign request {} to DB", rid);
	}

	public long check(final String rid, final String userId) {
		log.info("Req{}: Check accounts of user {}", rid, userId);
		//
		log.info("Query cash account of {}", rid, userId);
		Future<Long> cashFt = threadPool.submit(new Callable<Long>() {
			@Override
			public Long call() throws Exception {
				long cash = Math.round(Math.random() * 10000);
				log.info("Req{}: User {} cash account = {}", rid, userId, cash);
				return cash;
			}
		});
		log.info("Query stock account of {}", rid, userId);
		Future<Long> stockFt = threadPool.submit(new Callable<Long>() {
			@Override
			public Long call() throws Exception {
				long stock = Math.round(Math.random() * 10000);
				log.info("Req{}: User {} stock account = {}", rid, userId, stock);
				return stock;
			}
		});
		log.info("Query fund account of {}", rid, userId);
		Future<Long> fundFt = threadPool.submit(new Callable<Long>() {
			@Override
			public Long call() throws Exception {
				long fund = Math.round(Math.random() * 10000);
				log.info("Req{}: User {} fund account = {}", rid, userId, fund);
				return fund;
			}
		});
		//
		long total = 0L;
		try {
			total += cashFt.get(1000L, TimeUnit.MILLISECONDS);
			total += stockFt.get(1000L, TimeUnit.MILLISECONDS);
			total += fundFt.get(1000L, TimeUnit.MILLISECONDS);
		} catch (InterruptedException | ExecutionException | TimeoutException e) {
			log.error("Error on sum total money", e);
		}
		log.info("User {} total asset = {}", userId, total);
		return total;
	}

	public boolean login(User u) throws InterruptedException {
		Thread.sleep(10L);
		log.info("User {} login with encode {}", u.getName(), encode);
		if ("Mac_J".equals(u.getName()) && "123".equals(u.getPassword())) {
			u.setId("00000000000000000000000000000000");
			return true;
		}
		return false;
	}
}
